home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 2 / Atari Mega Archive CD - Volume 2.iso / minix / up1510b.tgz / up1510b / src / commands / unshar.c < prev    next >
C/C++ Source or Header  |  1990-07-23  |  7KB  |  340 lines

  1. /* unshar - extract files from a shell archive    Author: Warren Toomey */
  2.  
  3.  
  4. /* Unshar - extract files from shell archive
  5.  *
  6.  * Written by Warren Toomey [wkt@csadfa.oz.au@munnari.oz@uunet.uu.net] You may
  7.  * freely copy or give away this source as long as this notice remains
  8.  * intact.
  9.  *
  10.  * Definitions used by unshar
  11.  */
  12.  
  13.  
  14. #include <stdio.h>
  15.  
  16. /* Methods of unsharing */
  17. #define UNKNOWN    0
  18. #define BRUTAL    1
  19.  
  20. /* Whitespace indicators */
  21. #define WHITE    0
  22. #define NOWHITE 1
  23.  
  24. /* Leading character indicators */
  25. #define NOX    0
  26. #define YESX    1
  27.  
  28. /* Emulation types available */
  29.  
  30. #define NUMTOKS    4        /* Must change NUMTOKS to equal the */
  31.  /* Define UNKNOWN  0 *//* number of emulation types */
  32. #define SED       1
  33. #define GRES        2
  34. #define CAT       3
  35.  
  36. /* The list of emulation types. */
  37. static char *token[NUMTOKS]=
  38. {
  39.   "",
  40.   "sed",
  41.   "gres",
  42.   "cat"
  43. };
  44.  
  45.  
  46. /* Misc. constants */
  47. #define BUFSIZE    512        /* Size of line buffer */
  48.  
  49. /* Global variables */
  50. int table;            /* Generate a table, or extract */
  51. int verbose;            /* Unshar verbosely - debugging */
  52. int numext;            /* Number of files to extract */
  53. int binfile;            /* Binary file - err indicator */
  54. char *exfile[100];        /* Files to extract */
  55.  
  56.  
  57. #define getline(x,y)    fgetline(stdin,x,y)
  58.  
  59. int fgetline(zin, how, buf)    /* Get a line from a file */
  60. FILE *zin;
  61. int how;            /* Ignore leading whitespace if */
  62. char *buf;            /* how == NOWHITE */
  63. {
  64.   int ch = 0;
  65.  
  66.   *buf = 0;            /* Null the buffer */
  67.   if (how == NOWHITE) {        /* If skip any whitespace */
  68.     while (((ch = fgetc(zin)) == ' ') || (ch == '\t'));
  69.     if (ch == EOF) return(EOF);    /* Returning EOF or 0 */
  70.     if (ch == '\n') return (0);
  71.     *buf++ = ch;        /* Put char in buffer */
  72.   }
  73.   while ((ch = fgetc(zin)) != '\n') {    /* Now get the line */
  74.     if (ch == EOF) {
  75.         *buf = 0;
  76.         return(EOF);
  77.     }
  78.     if (ch > 127) {
  79.         binfile = 1;
  80.         return(0);
  81.     }
  82.     *buf++ = ch;
  83.   }
  84.  
  85.   *buf = 0;            /* Finally null-terminate the buffer */
  86.   return(0);            /* and return */
  87. }
  88.  
  89.  
  90.  
  91. char *getstring(buf)        /* Get the next string from the buffer */
  92. char *buf;            /* ignoring any quotes */
  93. {
  94.   char out[BUFSIZE];
  95.   char *temp = out;
  96.   char inquotes = 0, ok = 1;
  97.   while ((*buf == ' ') || (*buf == '\t'))
  98.     buf++;            /* Skip whitespace */
  99.  
  100.   if (verbose) printf("In getstring...\n");
  101.   *temp = 0;
  102.   while (ok) {            /* Parse line */
  103.     switch (*buf) {
  104.         case '\"':
  105.         case '\'':
  106.         buf++;
  107.         inquotes = !inquotes;    /* Toggle inquotes */
  108.         break;
  109.         case 0:
  110.         case '\n':        /* Stop on <, >, NULL */
  111.         case '>':        /* \n, and sometimes */
  112.             case '<':    ok = 0;    break;    /* space & tab */
  113.         case '\t':
  114.         case ' ':
  115.         if (!inquotes) ok = 0;
  116.         case '\\':
  117.         if (!inquotes) {/* Ignore backquotes */
  118.             buf++;
  119.             break;
  120.         }
  121.         default:
  122.         *temp++ = *buf++;    /* Copy chars :-) */
  123.     }
  124.   }
  125.   *temp = 0;
  126.   if (verbose) printf("Returning *%s*\n", out);
  127.   return(out);
  128. }
  129.  
  130.  
  131. int firstword(buf)            /* Return token value of first word */
  132. char *buf;            /* in the buffer. Assume no leading */
  133. {                /* whitespace in the buffer */
  134.   int i;
  135.  
  136.   for (i = 1; i < NUMTOKS; i++)
  137.     if (strncmp(buf, token[i], strlen(token[i])) == 0) return(i);
  138.  
  139.   return(UNKNOWN);
  140. }
  141.  
  142.  
  143. int mustget(s1)            /* Return 1 if s1 is in the list of  */
  144. char *s1;            /* files to extract. Return 0 if not */
  145. {
  146.   int i;
  147.  
  148.   if (numext == 0) return(0);
  149.   for (i = 0; i < numext; i++)
  150.     if (!strcmp(s1, exfile[i])) return(1);
  151.   return(0);
  152. }
  153.  
  154.  
  155. void extract(how, file, end, lead)    /* Extract file, up until end word */
  156. int how;            /* If how==YESX, then ignore lead   */
  157. char *file;            /* character on every line */
  158. char *end;
  159. int lead;
  160. {
  161.   FILE *zout;
  162.   char line[BUFSIZE];
  163.   char *temp;
  164.   int ch;
  165.  
  166.   zout = fopen(file, "w");    /* Open output file */
  167.   if (zout == NULL) {
  168.     perror("unshar1");
  169.     return;
  170.   }
  171.   while (1) {
  172.     binfile = 0;
  173.     ch = getline(WHITE, line);    /* Get a line of file */
  174.     temp = line;
  175.     if (binfile || (ch == EOF)) {
  176.         fprintf(zout, "%s\n", line);
  177.         fclose(zout);
  178.         return;
  179.     }
  180.     if ((how == YESX) && (*temp == lead)) temp++;    /* Skip any lead */
  181.  
  182.     if (strcmp(temp, end) == 0) {    /* If end word */
  183.         fclose(zout);    /* close the file */
  184.         return;
  185.     }
  186.     fprintf(zout, "%s\n", temp);
  187.   }
  188. }
  189.  
  190.  
  191. void getnames(buf, file, word)    /* Get the file & end word */
  192. char *buf, *file, *word;    /* from the buffer */
  193. {
  194.   char *temp;
  195.  
  196.   temp = buf;
  197.   if (verbose) printf("Getnames: buf is %s\n", buf);
  198.  
  199.   while (*temp != 0) {        /* Scan along buffer */
  200.     switch (*temp) {    /* Get file or end word */
  201.         case '>':
  202.         strcpy(file, getstring(++temp));    /* Get the file name */
  203.         break;
  204.         case '<':
  205.         if (*(++temp) == '<') ++temp;    /* Skip 2nd < */
  206.         strcpy(word, getstring(temp));    /* Get next word */
  207.         break;
  208.         default:
  209.         temp++;
  210.     }
  211.   }
  212. }
  213.  
  214.  
  215.  
  216. void disembowel()
  217. {                /* Unshar brutally! */
  218.   char buf[BUFSIZE];        /* Line buffer */
  219.   char file[BUFSIZE];        /* File name */
  220.   char word[BUFSIZE];        /* Word buffer */
  221.   int ch, x;
  222.  
  223.   if (verbose) printf("Entering disembowel\n");
  224.   x = 'X';            /* Leading X character */
  225.   while (1) {
  226.     binfile = 0;
  227.     ch = getline(NOWHITE, buf);    /* Get a line from file */
  228.     if (ch == EOF) return;
  229.     if (binfile) continue;
  230.  
  231.     switch (firstword(buf)) {    /* Extract, depending on first word */
  232.         case CAT:
  233.         if (verbose) printf("About to do getnames\n");
  234.         getnames(buf, file, word);
  235.         if (table == 0) {
  236.             if ((numext == 0) || (mustget(file))) {
  237.                 printf("unshar: Extracting  %s\n", file);
  238.                 if (verbose)
  239.                     printf("        stopping at %s\n", word);
  240.                 extract(NOX, file, word, x);
  241.             }
  242.         } else
  243.             printf("  %s\n", file);
  244.         break;
  245.         case GRES:
  246.         case SED:
  247.         if (verbose) printf("About to do getnames\n");
  248.         getnames(buf, file, word);
  249.         if (table == 0) {
  250.             if ((numext == 0) || (mustget(file))) {
  251.                 printf("unshar: Extracting  %s\n", file);
  252.                 if (verbose)
  253.                     printf("        stopping at %s\n", word);
  254.                 extract(YESX, file, word, x);
  255.             }
  256.         } else
  257.             printf("  %s\n", file);
  258.         break;
  259.         default:
  260.         break;
  261.     }
  262.   }
  263. }
  264.  
  265.  
  266.  
  267. usage()
  268. {
  269.   fprintf(stderr, "Usage: unshar [-t] [-b] [-v] [-xfile] [file(s)]\n");
  270.   exit(0);
  271. }
  272.  
  273.  
  274. main(argc, argv)
  275. int argc;
  276. char *argv[];
  277. {
  278.   extern int optind;
  279.   extern char *optarg;
  280.   int i, c, first;
  281.  
  282.   FILE *zin;            /* Dummy file descriptor */
  283.   int method;            /* Method of unsharing */
  284.  
  285.   method = BRUTAL;        /* Only BRUTAL currently available */
  286.   table = 0;            /* Don't generate a table */
  287.   verbose = 0;            /* Nor be very verbose */
  288.   numext = 0;            /* Initially no files to extract */
  289.  
  290.  
  291.   while ((c = getopt(argc, argv, "x:tbv")) != EOF) switch (c) {
  292.         case 't':
  293.         table = 1;    /* Get the various options */
  294.         break;
  295.             case 'b':    method = BRUTAL;    break;
  296.             case 'v':    verbose = 1;    break;
  297.         case 'x':
  298.         exfile[numext] = (char *) malloc(strlen(optarg) + 1);
  299.         strcpy(exfile[numext++], optarg);
  300.         break;
  301.         default:
  302.         usage();
  303.     }
  304.  
  305.   if (argc == 1)
  306.     first = argc;        /* Find first file argument */
  307.   else
  308.     for (first = 1; first < argc; first++)
  309.         if (argv[first][0] != '-') break;
  310.  
  311.   if (first == argc) {        /* If no file argument *//* use stdin only */
  312.     switch (method) {
  313.         case BRUTAL:
  314.         disembowel();    /* Unshar brutally! */
  315.         break;
  316.         default:
  317.         fprintf(stderr, "unshar: Unknown method of unsharing\n");
  318.         exit(1);
  319.     }
  320.   } else
  321.     for (i = first; i < argc; i++) {    /* open stdio with every
  322.                          * file */
  323.         if (table) printf("%s:\n", argv[i]);
  324.         fclose(stdin);
  325.         if ((zin = fopen(argv[i], "r")) == NULL) {
  326.             perror("unshar2");
  327.             exit(1);
  328.         }
  329.         switch (method) {
  330.             case BRUTAL:
  331.             disembowel();    /* Unshar brutally! */
  332.             break;
  333.             default:
  334.             fprintf(stderr, "unshar: Unknown method of unsharing\n");
  335.             exit(1);
  336.         }
  337.     }
  338.   exit(0);
  339. }
  340.